# Justfile for netdisk-front CI/CD
# Usage: just <command> [args...]
# Variables can be set via environment variables or passed as arguments
#
# Note: Frontend is static files, no compilation needed.
# Docker build simply copies src/ directory to nginx container.

# -----------------------------
# Default variables (can be overridden via environment or command line)
# -----------------------------
DEFAULT_PROJECT_ROOT := "../.."
DEFAULT_REGISTRY := "192.168.0.104:5000"
DEFAULT_REGISTRY_NAMESPACE := "library"
DEFAULT_FRONTEND_IMAGE_NAME := "netdisk-front"
# Note: IMAGE_TAG defaults to git commit hash if not specified
DEFAULT_IMAGE_TAG := "latest"

DEFAULT_K8S_NAMESPACE := "netdisk"
DEFAULT_RELEASE_FRONTEND := "netdisk-front"
DEFAULT_HELM_CHART_PATH := "helm/netdisk-front"
DEFAULT_KUBECONFIG_PATH := "~/.kube/config"

# -----------------------------
# Get Git Info: Extract git commit hash from current repository
# -----------------------------
get-git-info PROJECT_ROOT='':
    #!/usr/bin/env bash
    set -e
    
    if [ -n "$PROJECT_ROOT" ]; then
        FINAL_PROJECT_ROOT="$PROJECT_ROOT"
    else
        FINAL_PROJECT_ROOT="${PROJECT_ROOT:-{{DEFAULT_PROJECT_ROOT}}}"
    fi
    
    # Convert to absolute path
    FINAL_PROJECT_ROOT_ABS=$(cd "${FINAL_PROJECT_ROOT}" && pwd)
    
    cd "${FINAL_PROJECT_ROOT_ABS}"
    
    # Check if it's a git repository
    if [ ! -d ".git" ]; then
        echo "Warning: Not a git repository, cannot get commit hash" >&2
        GIT_COMMIT_HASH="unknown"
        GIT_COMMIT_FULL="unknown"
        GIT_BRANCH="unknown"
    else
        GIT_COMMIT_HASH=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
        GIT_COMMIT_FULL=$(git rev-parse HEAD 2>/dev/null || echo "unknown")
        GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
    fi
    
    # Save git info to artifact file
    ARTIFACT_DIR="${FINAL_PROJECT_ROOT_ABS}/.artifacts"
    mkdir -p "${ARTIFACT_DIR}"
    {
        echo "GIT_COMMIT_HASH=${GIT_COMMIT_HASH}"
        echo "GIT_COMMIT_FULL=${GIT_COMMIT_FULL}"
        echo "GIT_BRANCH=${GIT_BRANCH}"
    } > "${ARTIFACT_DIR}/git-info.env"
    
    echo "Git commit info: ${GIT_COMMIT_HASH} (${GIT_COMMIT_FULL}) on branch ${GIT_BRANCH}"

# -----------------------------
# Push: Build Docker image and push to registry
# -----------------------------
push PROJECT_ROOT='' REGISTRY='' REGISTRY_NAMESPACE='' FRONTEND_IMAGE_NAME='' IMAGE_TAG='':
    #!/usr/bin/env bash
    set -e
    
    # Save justfile directory (just executes recipes from the directory containing the justfile)
    JUSTFILE_DIR="$(pwd)"
    JUSTFILE_PATH="${JUSTFILE_DIR}/justfile"
    
    # Priority: provided args (if not empty) > environment variables > defaults
    FINAL_PROJECT_ROOT="${PROJECT_ROOT:-{{DEFAULT_PROJECT_ROOT}}}"
    FINAL_REGISTRY="${REGISTRY:-{{DEFAULT_REGISTRY}}}"
    FINAL_REGISTRY_NAMESPACE="${REGISTRY_NAMESPACE:-{{DEFAULT_REGISTRY_NAMESPACE}}}"
    FINAL_FRONTEND_IMAGE_NAME="${FRONTEND_IMAGE_NAME:-{{DEFAULT_FRONTEND_IMAGE_NAME}}}"
    
    # Convert to absolute path
    FINAL_PROJECT_ROOT_ABS=$(cd "${FINAL_PROJECT_ROOT}" && pwd)
    
    cd "${FINAL_PROJECT_ROOT_ABS}"
    
    # Get git commit hash
    just --justfile "${JUSTFILE_PATH}" get-git-info PROJECT_ROOT="${FINAL_PROJECT_ROOT_ABS}"
    
    # Load git commit hash from artifact file
    ARTIFACT_DIR="${FINAL_PROJECT_ROOT_ABS}/.artifacts"
    GIT_INFO_FILE="${ARTIFACT_DIR}/git-info.env"
    if [ -f "${GIT_INFO_FILE}" ]; then
        source "${GIT_INFO_FILE}"
    else
        # Fallback: get commit hash directly
        if [ -d ".git" ]; then
            GIT_COMMIT_HASH=$(git rev-parse --short HEAD)
        else
            GIT_COMMIT_HASH="unknown"
        fi
    fi
    
    # Use provided IMAGE_TAG if specified, otherwise use git commit hash
    if [ -n "$IMAGE_TAG" ]; then
        FINAL_IMAGE_TAG="$IMAGE_TAG"
    else
        FINAL_IMAGE_TAG="${GIT_COMMIT_HASH}"
        if [ "${FINAL_IMAGE_TAG}" = "unknown" ]; then
            FINAL_IMAGE_TAG="latest"
        fi
        echo "Using git commit hash as image tag: ${FINAL_IMAGE_TAG}"
    fi
    
    IMAGE_REPO="${FINAL_REGISTRY}/${FINAL_REGISTRY_NAMESPACE}/${FINAL_FRONTEND_IMAGE_NAME}"
    IMAGE_FULL="${IMAGE_REPO}:${FINAL_IMAGE_TAG}"
    
    echo "Building Docker image: ${IMAGE_FULL}"
    echo "  REGISTRY=${FINAL_REGISTRY}"
    echo "  REGISTRY_NAMESPACE=${FINAL_REGISTRY_NAMESPACE}"
    echo "  FRONTEND_IMAGE_NAME=${FINAL_FRONTEND_IMAGE_NAME}"
    echo "  IMAGE_TAG=${FINAL_IMAGE_TAG}"
    echo "  Project root: ${FINAL_PROJECT_ROOT_ABS}"
    
    # Check if Dockerfile exists
    if [ ! -f "${FINAL_PROJECT_ROOT_ABS}/Dockerfile" ]; then
        echo "Error: Dockerfile not found at ${FINAL_PROJECT_ROOT_ABS}/Dockerfile" >&2
        exit 1
    fi
    
    # Login to registry if credentials provided
    if [ -n "${REGISTRY_USER:-}" ] && [ -n "${REGISTRY_PASSWORD:-}" ]; then
        echo "Logging in to registry ${FINAL_REGISTRY}..."
        echo "${REGISTRY_PASSWORD}" | docker login "${FINAL_REGISTRY}" -u "${REGISTRY_USER}" --password-stdin
    else
        echo "No REGISTRY_USER/REGISTRY_PASSWORD provided; skipping docker login."
    fi
    
    # Build image
    echo "Building Docker image..."
    docker build --no-cache -t "${IMAGE_FULL}" -f "${FINAL_PROJECT_ROOT_ABS}/Dockerfile" "${FINAL_PROJECT_ROOT_ABS}"
    
    # Push image
    echo "Pushing ${IMAGE_FULL}..."
    PUSH_OUTPUT=$(docker push "${IMAGE_FULL}" 2>&1)
    PUSH_EXIT_CODE=$?
    
    if [ $PUSH_EXIT_CODE -ne 0 ]; then
        echo "Error: Failed to push image ${IMAGE_FULL}" >&2
        echo "$PUSH_OUTPUT" >&2
        exit 1
    fi
    
    # Verify push was successful by checking for digest in output
    if echo "$PUSH_OUTPUT" | grep -q "digest:"; then
        echo "Image pushed successfully: ${IMAGE_FULL}"
        DIGEST=$(echo "$PUSH_OUTPUT" | grep "digest:" | sed 's/.*digest: //' | awk '{print $1}')
        echo "  Digest: ${DIGEST}"
    else
        echo "Warning: Could not find digest in push output, but push command succeeded"
        echo "  Assuming image was pushed successfully"
    fi
    
    # Also push latest tag if not already latest
    if [ "${FINAL_IMAGE_TAG}" != "latest" ]; then
        docker tag "${IMAGE_FULL}" "${IMAGE_REPO}:latest"
        docker push "${IMAGE_REPO}:latest"
        echo "Also pushed ${IMAGE_REPO}:latest"
    fi
    
    # Save image info to artifact file for deploy command
    ARTIFACT_DIR="${FINAL_PROJECT_ROOT_ABS}/.artifacts"
    mkdir -p "${ARTIFACT_DIR}"
    {
        echo "IMAGE_REPO=${IMAGE_REPO}"
        echo "IMAGE_TAG=${FINAL_IMAGE_TAG}"
        echo "IMAGE_FULL=${IMAGE_FULL}"
        echo "GIT_COMMIT_HASH=${GIT_COMMIT_HASH}"
    } > "${ARTIFACT_DIR}/image-info.env"
    echo "Image info saved to ${ARTIFACT_DIR}/image-info.env"
    echo "  Image: ${IMAGE_FULL}"
    echo "  Git commit: ${GIT_COMMIT_HASH}"
    
    echo "Push complete: ${IMAGE_FULL}"

# -----------------------------
# Deploy: Deploy to Kubernetes using Helm
# -----------------------------
deploy PROJECT_ROOT='' REGISTRY='' REGISTRY_NAMESPACE='' FRONTEND_IMAGE_NAME='' IMAGE_TAG='' K8S_NAMESPACE='' RELEASE_FRONTEND='' HELM_CHART_PATH='' KUBECONFIG_PATH='':
    #!/usr/bin/env bash
    set -e
    
    # Save justfile directory (just executes recipes from the directory containing the justfile)
    JUSTFILE_DIR="$(pwd)"
    JUSTFILE_PATH="${JUSTFILE_DIR}/justfile"
    
    # Priority: provided args (if not empty) > environment variables > defaults
    FINAL_PROJECT_ROOT="${PROJECT_ROOT:-{{DEFAULT_PROJECT_ROOT}}}"
    FINAL_REGISTRY="${REGISTRY:-{{DEFAULT_REGISTRY}}}"
    FINAL_REGISTRY_NAMESPACE="${REGISTRY_NAMESPACE:-{{DEFAULT_REGISTRY_NAMESPACE}}}"
    FINAL_FRONTEND_IMAGE_NAME="${FRONTEND_IMAGE_NAME:-{{DEFAULT_FRONTEND_IMAGE_NAME}}}"
    FINAL_K8S_NAMESPACE="${K8S_NAMESPACE:-{{DEFAULT_K8S_NAMESPACE}}}"
    FINAL_RELEASE_FRONTEND="${RELEASE_FRONTEND:-{{DEFAULT_RELEASE_FRONTEND}}}"
    FINAL_HELM_CHART_PATH="${HELM_CHART_PATH:-{{DEFAULT_HELM_CHART_PATH}}}"
    FINAL_KUBECONFIG_PATH="${KUBECONFIG_PATH:-{{DEFAULT_KUBECONFIG_PATH}}}"
    
    # Convert to absolute path
    FINAL_PROJECT_ROOT_ABS=$(cd "${FINAL_PROJECT_ROOT}" && pwd)
    
    cd "${FINAL_PROJECT_ROOT_ABS}"
    
    IMAGE_REPO="${FINAL_REGISTRY}/${FINAL_REGISTRY_NAMESPACE}/${FINAL_FRONTEND_IMAGE_NAME}"
    
    # Try to load image info from artifact file (if push was run before)
    ARTIFACT_FILE="${FINAL_PROJECT_ROOT_ABS}/.artifacts/image-info.env"
    if [ -f "${ARTIFACT_FILE}" ]; then
        echo "Found image artifact file, loading image info..."
        source "${ARTIFACT_FILE}"
        # Ensure FINAL_IMAGE_TAG is set from artifact file
        FINAL_IMAGE_TAG="${IMAGE_TAG}"
        echo "Using image from artifact: ${IMAGE_FULL}"
        echo "  Image tag: ${FINAL_IMAGE_TAG}"
        echo "  Git commit: ${GIT_COMMIT_HASH}"
        echo "  (This ensures the same image that was pushed is deployed)"
    else
        # Get git commit hash
        just --justfile "${JUSTFILE_PATH}" get-git-info PROJECT_ROOT="${FINAL_PROJECT_ROOT_ABS}"
        
        GIT_INFO_FILE="${FINAL_PROJECT_ROOT_ABS}/.artifacts/git-info.env"
        if [ -f "${GIT_INFO_FILE}" ]; then
            source "${GIT_INFO_FILE}"
        else
            if [ -d ".git" ]; then
                GIT_COMMIT_HASH=$(git rev-parse --short HEAD)
            else
                GIT_COMMIT_HASH="unknown"
            fi
        fi
        
        # Use provided IMAGE_TAG if specified, otherwise use git commit hash
        if [ -n "$IMAGE_TAG" ]; then
            FINAL_IMAGE_TAG="$IMAGE_TAG"
        else
            FINAL_IMAGE_TAG="${GIT_COMMIT_HASH}"
            if [ "${FINAL_IMAGE_TAG}" = "unknown" ]; then
                FINAL_IMAGE_TAG="latest"
            fi
            echo "Using git commit hash as image tag: ${FINAL_IMAGE_TAG}"
        fi
        
        IMAGE_FULL="${IMAGE_REPO}:${FINAL_IMAGE_TAG}"
        echo "Warning: No image artifact file found at ${ARTIFACT_FILE}"
        echo "  Make sure to run 'just push' before 'just deploy', or use 'just all'"
        echo "  Proceeding with image: ${IMAGE_FULL}"
    fi
    
    # Validate that FINAL_IMAGE_TAG is not empty
    if [ -z "${FINAL_IMAGE_TAG}" ]; then
        echo "Error: IMAGE_TAG is empty! Cannot deploy." >&2
        echo "  Please run 'just push' first, or provide IMAGE_TAG parameter." >&2
        exit 1
    fi
    
    # Verify image exists in registry before deploying
    echo "Verifying image exists in registry: ${IMAGE_FULL}..."
    if docker manifest inspect "${IMAGE_FULL}" >/dev/null 2>&1; then
        echo "Image verified in registry: ${IMAGE_FULL}"
    else
        echo "Note: Could not verify image via manifest inspect (may not be supported by registry)"
        echo "  Proceeding with deployment - K8s will verify image availability during pull"
    fi
    
    echo "Deploying to Kubernetes..."
    echo "  Namespace: ${FINAL_K8S_NAMESPACE}"
    echo "  Release: ${FINAL_RELEASE_FRONTEND}"
    echo "  Image Repository: ${IMAGE_REPO}"
    echo "  Image Tag: ${FINAL_IMAGE_TAG}"
    echo "  Full Image: ${IMAGE_FULL}"
    echo "  Chart: ${FINAL_HELM_CHART_PATH}"
    
    # Double-check that FINAL_IMAGE_TAG is not empty
    if [ -z "${FINAL_IMAGE_TAG}" ]; then
        echo "Error: FINAL_IMAGE_TAG is empty! Cannot proceed with deployment." >&2
        exit 1
    fi
    
    # Check if kubectl and helm are available
    command -v kubectl >/dev/null 2>&1 || { echo "Error: kubectl not found" >&2; exit 1; }
    command -v helm >/dev/null 2>&1 || { echo "Error: helm not found" >&2; exit 1; }
    
    # Expand kubeconfig path
    KUBECONFIG_EXPANDED=$(eval echo "${FINAL_KUBECONFIG_PATH}")
    if [ ! -f "${KUBECONFIG_EXPANDED}" ]; then
        echo "Error: Kubeconfig not found at ${KUBECONFIG_EXPANDED}" >&2
        exit 1
    fi
    export KUBECONFIG="${KUBECONFIG_EXPANDED}"
    
    # Verify cluster connection
    kubectl version --client=true
    helm version
    
    # Ensure idempotency: create namespace if not exists
    kubectl get namespace "${FINAL_K8S_NAMESPACE}" >/dev/null 2>&1 || kubectl create namespace "${FINAL_K8S_NAMESPACE}"
    
    # Convert helm chart path to absolute (relative to project root)
    if [[ "${FINAL_HELM_CHART_PATH}" = /* ]]; then
        # Already absolute path
        HELM_CHART_ABS="${FINAL_HELM_CHART_PATH}"
    else
        # Relative path - resolve from project root
        HELM_CHART_ABS="${FINAL_PROJECT_ROOT_ABS}/${FINAL_HELM_CHART_PATH}"
    fi
    
    # Verify helm chart directory exists
    if [ ! -d "${HELM_CHART_ABS}" ]; then
        echo "Error: Helm chart directory not found: ${HELM_CHART_ABS}" >&2
        exit 1
    fi
    
    # Deploy with Helm (upgrade --install is idempotent)
    echo "Executing helm upgrade --install with:"
    echo "  image.repository=${IMAGE_REPO}"
    echo "  image.tag=${FINAL_IMAGE_TAG}"
    helm upgrade --install "${FINAL_RELEASE_FRONTEND}" "${HELM_CHART_ABS}" \
        --namespace "${FINAL_K8S_NAMESPACE}" \
        --set image.repository="${IMAGE_REPO}" \
        --set image.tag="${FINAL_IMAGE_TAG}" \
        --wait
    
    # Verify deployment is using the correct image
    echo "Verifying deployment..."
    DEPLOYED_IMAGE=$(kubectl get deployment -n "${FINAL_K8S_NAMESPACE}" "${FINAL_RELEASE_FRONTEND}" -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null || echo "")
    
    if [ -n "${DEPLOYED_IMAGE}" ]; then
        echo "Deployed image: ${DEPLOYED_IMAGE}"
        if [ "${DEPLOYED_IMAGE}" != "${IMAGE_FULL}" ]; then
            echo "Warning: Deployed image (${DEPLOYED_IMAGE}) differs from expected (${IMAGE_FULL})"
        else
            echo "✓ Image version verified: ${IMAGE_FULL}"
        fi
    else
        echo "Note: Could not verify deployed image (deployment may not exist yet)"
    fi
    
    echo "Deployment complete!"

# -----------------------------
# All: Run push and deploy in sequence
# -----------------------------
all PROJECT_ROOT='' REGISTRY='' REGISTRY_NAMESPACE='' FRONTEND_IMAGE_NAME='' IMAGE_TAG='' K8S_NAMESPACE='' RELEASE_FRONTEND='' HELM_CHART_PATH='' KUBECONFIG_PATH='':
    #!/usr/bin/env bash
    set -e
    # Save justfile directory (just executes recipes from the directory containing the justfile)
    JUSTFILE_DIR="$(pwd)"
    JUSTFILE_PATH="${JUSTFILE_DIR}/justfile"
    # Note: IMAGE_TAG is optional - if not provided, git commit hash will be used automatically
    just --justfile "${JUSTFILE_PATH}" push PROJECT_ROOT="$PROJECT_ROOT" REGISTRY="$REGISTRY" REGISTRY_NAMESPACE="$REGISTRY_NAMESPACE" FRONTEND_IMAGE_NAME="$FRONTEND_IMAGE_NAME" IMAGE_TAG="$IMAGE_TAG"
    just --justfile "${JUSTFILE_PATH}" deploy PROJECT_ROOT="$PROJECT_ROOT" REGISTRY="$REGISTRY" REGISTRY_NAMESPACE="$REGISTRY_NAMESPACE" FRONTEND_IMAGE_NAME="$FRONTEND_IMAGE_NAME" IMAGE_TAG="$IMAGE_TAG" K8S_NAMESPACE="$K8S_NAMESPACE" RELEASE_FRONTEND="$RELEASE_FRONTEND" HELM_CHART_PATH="$HELM_CHART_PATH" KUBECONFIG_PATH="$KUBECONFIG_PATH"

# -----------------------------
# Clean: Remove artifact directory
# -----------------------------
clean PROJECT_ROOT='':
    #!/usr/bin/env bash
    set -e
    if [ -n "$PROJECT_ROOT" ]; then
        FINAL_PROJECT_ROOT="$PROJECT_ROOT"
    else
        FINAL_PROJECT_ROOT="${PROJECT_ROOT:-{{DEFAULT_PROJECT_ROOT}}}"
    fi
    
    # Convert to absolute path
    FINAL_PROJECT_ROOT_ABS=$(cd "${FINAL_PROJECT_ROOT}" && pwd)
    ARTIFACT_DIR="${FINAL_PROJECT_ROOT_ABS}/.artifacts"
    
    if [ -d "${ARTIFACT_DIR}" ]; then
        echo "Removing artifact directory: ${ARTIFACT_DIR}"
        rm -rf "${ARTIFACT_DIR}"
        echo "Clean complete"
    else
        echo "Artifact directory does not exist: ${ARTIFACT_DIR}"
    fi

